package com.heshuo.basic.dao.impl;

import java.io.Serializable;
import java.sql.SQLException;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.hibernate.HibernateException;
import org.hibernate.LockMode;
import org.hibernate.Query;
import org.hibernate.Session;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.orm.hibernate3.HibernateCallback;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;
import java.lang.reflect.ParameterizedType;

import com.heshuo.basic.dao.IBaseHibernateDAO;
import com.heshuo.basic.page.PageUtil;
import com.heshuo.util.COMMON;
/**
 *  DAO操作基类  
 * @author zz
 *
 * @param <T>
 *        POJO实体
 * @param <ID>
 * 			ID
 */
public class BaseHibernateDAOImpl<T,  ID extends Serializable> extends HibernateDaoSupport implements IBaseHibernateDAO<T, ID>{

	private static final Logger log = LoggerFactory.getLogger(BaseHibernateDAOImpl.class);
	private Class<T> persistentClass;

	public Class<T> getPersistentClass() {    
        return this.persistentClass;    
    }    
        
    /**   
     * 默认构造函数，用于获取范型T的带有类型化信息的Class对象   
     */   
    @SuppressWarnings("unchecked")    
    public BaseHibernateDAOImpl() {    
        this.persistentClass = (Class<T>) ((ParameterizedType) this.getClass().getGenericSuperclass()).getActualTypeArguments()[0];     
    }
    
	
	public void save(T entity) {
		// TODO Auto-generated method stub
		 getHibernateTemplate().save(entity);   
	}

	
	public void delete(T entity) {
		// TODO Auto-generated method stub
		getHibernateTemplate().delete(entity); 
	}

	
	public List<T> findAll(Class<T> entityClass) {
		// TODO Auto-generated method stub
		//System.out.println("=====" + getHibernateTemplate().find("from " + entityClass.getName()).size());
		
		return getHibernateTemplate().find("from " + entityClass.getName());  
	}

	
	public void saveOrUpdate(T entity) {
		// TODO Auto-generated method stub
		getHibernateTemplate().saveOrUpdate(entity);   
	}

	
	public T findById(Class<T> entityClass, ID id) {
		// TODO Auto-generated method stub
		return (T) getHibernateTemplate().get(entityClass, id);   
	}
	
	public T findById(ID id) {
		// TODO Auto-generated method stub
		return (T) getHibernateTemplate().get(this.getPersistentClass(), id);   
	}
	
	public List<T> find(String hql, Object... values) {
		// TODO Auto-generated method stub
		return getHibernateTemplate().find(hql, values);
	}
	
	public List<T> find(final String hql, final Map paramsMap) {
		// TODO Auto-generated method stub
		
		return getHibernateTemplate().execute(new HibernateCallback() {   
            public Object doInHibernate(Session s)   
                    throws HibernateException, SQLException {   
                Query query = createQuery(s, hql, paramsMap);   
                return query.list();   
            }   
        });
	}
	
	public T findUnique(final String hql,final Object... values) {
		// TODO Auto-generated method stub
		return (T) getHibernateTemplate().execute(new HibernateCallback() {   
            public Object doInHibernate(Session s)   
                    throws HibernateException, SQLException {   
                Query query = createQuery(s, hql, values);   
                return query.uniqueResult();   
            }   
        });
	}
	
	public T findUnique(final String hql,final Map paramsMap) {
		// TODO Auto-generated method stub
		return (T) getHibernateTemplate().execute(new HibernateCallback() {   
            public Object doInHibernate(Session s)   
                    throws HibernateException, SQLException {   
                Query query = createQuery(s, hql, paramsMap);   
                return query.uniqueResult();   
            }   
        });
	}
	
	public int findInt(final String hql, final Object... values) {
		// TODO Auto-generated method stub
		return COMMON.null2Int(findUnique(hql, values)); 
	}
	
	public int findInt(final String hql, final Map paramsMap) {
		// TODO Auto-generated method stub
		return COMMON.null2Int(findUnique(hql, paramsMap)); 
	}
	
	public int findTotalCount(Class<T> entityClass,final String where,
			final Object... values) {
		// TODO Auto-generated method stub
		String hql = "select count(e) from " + entityClass.getName() + " as e "  
                + where;   
        return findInt(hql, values);   

	}
	
	public int findTotalCount(Class<T> entityClass,final String where,
			final  Map paramsMap) {
		// TODO Auto-generated method stub
		String hql = "select count(e) from " + entityClass.getName() + " as e "  
                + where;   
        return findInt(hql, paramsMap);   

	}
	
	public int findTotalCount(Class<T> entityClass) {
		// TODO Auto-generated method stub
		return findTotalCount(entityClass, "");
	}

	
	public List<T> findByProperty(Class<T> entityClass, String propertyName,
			Object value) {
		// TODO Auto-generated method stub
		String queryStr = "from " + entityClass.getName()   
                + " as model where model." + propertyName + "=?";   
        return getHibernateTemplate().find(queryStr, value);
	}

	
	public List<T> findByExample(T entity) {
		// TODO Auto-generated method stub
		List<T> results = getHibernateTemplate().findByExample(entity);   
        return results; 
	}

	
	public T merge(T entity) {
		// TODO Auto-generated method stub
		T result = (T) getHibernateTemplate().merge(entity);   
        return result; 
	}

	
	public void attachClean(T entity) {
		// TODO Auto-generated method stub
		getHibernateTemplate().lock(entity, LockMode.NONE);
	}

	
	public PageUtil<T> findByPage(final PageUtil<T> pageUtil,final String hql,
			final Object... values) {
		// TODO Auto-generated method stub
		return (PageUtil<T>) getHibernateTemplate().execute(   
                new HibernateCallback() {   
                    public Object doInHibernate(Session s)   
                            throws HibernateException, SQLException {   
                        Query query = createQuery(s, hql, values);   
                        query.setFirstResult(pageUtil.getPageStart());   
                        query.setMaxResults(pageUtil.getPageSize());   
                        pageUtil.setResult(query.list());   
                        return pageUtil;   
                    }   
                });  
	}
	
	public PageUtil<T> findByPage(final PageUtil<T> pageUtil,final String hql,
			final Map paramsMap) {
		// TODO Auto-generated method stub
		return (PageUtil<T>) getHibernateTemplate().execute(   
                new HibernateCallback() {   
                    public Object doInHibernate(Session s)   
                            throws HibernateException, SQLException {   
                        Query query = createQuery(s, hql, paramsMap);   
                        query.setFirstResult(pageUtil.getPageStart());   
                        query.setMaxResults(pageUtil.getPageSize());   
                        pageUtil.setResult(query.list());   
                        return pageUtil;   
                    }   
                });  
	}
	
	
	public List<T> findByPage(final int pageNo,final int pageSize,final String hql,	final Object... values) {
		// TODO Auto-generated method stub
		return  getHibernateTemplate().execute(   
                new HibernateCallback() {   
                    public Object doInHibernate(Session s)   
                            throws HibernateException, SQLException {   
                        Query query = createQuery(s, hql, values);
                        if (0==pageNo){
                        	query.setFirstResult(1);   
                        	query.setMaxResults(pageSize);
                        }else{
                        	query.setFirstResult((pageNo-1)*pageSize);   
                        	query.setMaxResults(pageSize);
                        }   
                        return query.list();   
                    }   
                });  
	}
	
	public List<T> findByPage(final int pageNo,final int pageSize,final String hql,
			final Map paramsMap) {
		// TODO Auto-generated method stub
		return  getHibernateTemplate().execute(   
                new HibernateCallback() {   
                    public Object doInHibernate(Session s)   
                            throws HibernateException, SQLException {   
                        Query query = createQuery(s, hql, paramsMap);   
                        if (0==pageNo){
                        	query.setFirstResult(1);   
                        	query.setMaxResults(pageSize);
                        }else{
                        	query.setFirstResult((pageNo-1)*pageSize);   
                        	query.setMaxResults(pageSize);
                        }  
                        return query.list();   
                    }   
                });  
	}
	
	public Query createQuery(Session session, String hql, Object... objects) {
		// TODO Auto-generated method stub
		Query query = session.createQuery(hql);   
        if (objects != null) {   
            for (int i = 0; i < objects.length; i++) {   
                query.setParameter(i, objects[i]);   
            }   
        }   
        return query;
	}
	
	public Query createQuery(Session session, String hql, Map paramsMap) {
		// TODO Auto-generated method stub
		Query query = session.createQuery(hql);   
        if (paramsMap != null) {
        	Iterator it = paramsMap.entrySet().iterator();
    		while (it.hasNext()){
    			Map.Entry entry = (Map.Entry) it.next() ;
    			query.setParameter(entry.getKey().toString(), entry.getValue());
    			
    		}
               
        }   
        return query;
	}

	
	public List<T> findBySql(final String sql,final String obejctName, Map paramsMap) {
		// TODO Auto-generated method stub
		return  getHibernateTemplate().execute(   
                new HibernateCallback() {   
                    public Object doInHibernate(Session s)   
                            throws HibernateException, SQLException {   
                        Query query = s.createSQLQuery(sql).addEntity(obejctName);   
                        return query.list();   
                    }   
                });
	}

	
	public List<T> findSqlByPage(final int pageNo,final int pageSize,final String sql,final String objectName,final
			Map paramsMap) {
		// TODO Auto-generated method stub
		return  getHibernateTemplate().execute(   
                new HibernateCallback() {   
                    public Object doInHibernate(Session s)   
                            throws HibernateException, SQLException {   
                        Query query = s.createSQLQuery(sql).addEntity(objectName);   
                        if (0==pageNo){
                        	query.setFirstResult(1);   
                        	query.setMaxResults(pageSize);
                        }else{
                        	query.setFirstResult((pageNo-1)*pageSize);   
                        	query.setMaxResults(pageSize);
                        }  
                        return query.list();   
                    }   
                });  
	}
	
	
}
